%% @author wenqi_zheng
%% @doc @todo Add description to tcp_server_sup.


-module(tcp_server_sup).
-behaviour(supervisor).
-export([init/1]).

%% ====================================================================
%% API functions
%% ====================================================================
-export([start/2]).

-define(MAX_RESTART, 5).
-define(MAX_TIME, 60).
-define(DEF_PORT, 2345).


start(_Type, _Args)->
	ListenPort = get_app_env(listen_port, ?DEF_PORT), 
	
	%% 启动应用程序，回调函数为 第一个 init 函数，根据参数匹配，参数为 [端口，客户端回调模块]
	%% 第一个 init 函数仅仅是启动了两个监控树
	supervisor:start_link({local, ?MODULE}, ?MODULE, [ListenPort, tcp_echo_fsm]).

%% ====================================================================
%% Behavioural functions
%% ====================================================================

%% init/1
%% ====================================================================
%% @doc <a href="http://www.erlang.org/doc/man/supervisor.html#Module:init-1">supervisor:init/1</a>
-spec init(Args :: term()) -> Result when
	Result :: {ok, {SupervisionPolicy, [ChildSpec]}} | ignore,
	SupervisionPolicy :: {RestartStrategy, MaxR :: non_neg_integer(), MaxT :: pos_integer()},
	RestartStrategy :: one_for_all
					 | one_for_one
					 | rest_for_one
					 | simple_one_for_one,
	ChildSpec :: {Id :: term(), StartFunc, RestartPolicy, Type :: worker | supervisor, Modules},
	StartFunc :: {M :: module(), F :: atom(), A :: [term()] | undefined},
	RestartPolicy :: permanent
				   | transient
				   | temporary,
	Modules :: [module()] | dynamic.
%% ====================================================================
init([Port, Module]) ->
	Procs = [{tcp_server_sup,
			  {tcp_listener, start_link, [Port, Module]},
			  permanent, 
			  2000,
			  worker,
			  [tcp_listener]
			 },
			 {tcp_client_sup,
			  {supervisor, start_link, [{local, tcp_client_sup}, ?MODULE, [Module]]},
			  permanent,
			  infinity,
			  supervisor,
			  []
			 }
			],
	{ok,{{one_for_one, ?MAX_RESTART, ?MAX_TIME}, Procs}};

 init([Module]) ->
	 {ok,    
	  %% 另外一种根监督树模式，simple_one_for_one策略子节点只能动态添加
	  {_SupFlags = {simple_one_for_one, ?MAX_RESTART, ?MAX_TIME},
	   [
		% TCP Client
		{   undefined,                               % Id       = internal id
			{Module,start_link,[]},                  % StartFun = {M, F, A}
			temporary,                               % Restart  = permanent | transient | temporary
			2000,                                    % Shutdown = brutal_kill | int() >= 0 | infinity
			worker,                                  % Type     = worker | supervisor
			[]                                       % Modules  = [Module] | dynamic
		}
	   ]
	  }
	 }.

%% ====================================================================
%% Internal functions
%% ====================================================================

get_app_env(Opt, Default) ->
	case application:get_env(application:get_application(), Opt) of
		{ok, Val} -> Val;
		_ ->
			case init:get_argument(Opt) of
				[[Val | _]] -> Val;
				error       -> Default
			end
	end.
